package com.atguigu.srb.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.atguigu.srb.base.exception.SrbException;
import com.atguigu.srb.common.result.ResultCodeEnum;
import com.atguigu.srb.entity.excel.DictExcelVo;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.srb.entity.Dict;
import com.atguigu.srb.service.DictService;
import com.atguigu.srb.mapper.DictMapper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;

/**
* @author 1
* @description 针对表【dict(数据字典)】的数据库操作Service实现
* @createDate 2025-04-25 22:00:32
*/
@Service
@Slf4j
public class DictServiceImpl extends ServiceImpl<DictMapper, Dict>
    implements DictService{
    @SneakyThrows  //抑制异常抛出： 不需要我们手动抛出异常  lombok的注解
    @Override
    public void exportDicts(HttpServletResponse response) {
        //1、查询要导出的数据：也可以带条件查询(需要接收前端的参数)
        // 字典表查询所有导出
        List<Dict> dicts = baseMapper.selectList(null);
        if(CollectionUtils.isEmpty(dicts)){
            throw new SrbException(ResultCodeEnum.QUERY_DATA_ERROR);
        }
        //2、将数据写到excel文件中导出文件：
        //2.1 自定义一个实体类： 用来映射excel文件中的行( 数据库表中的一行数据 对应java的一个对象  java的一个对象 对应excel文件的一行 ， 一列对应对象的一个属性值  )
        //2.2 将查询到的字典表数据转为  excel实体类集合
        List<DictExcelVo> excelVos = dicts.stream()
                .map(dict -> {
                    DictExcelVo dictExcelVo = new DictExcelVo();
                    //复制的要求： 两个类属性名 和类型一样 才可以复制成功( 还必须有getter/setter方法 )
                    BeanUtils.copyProperties(dict, dictExcelVo);
                    return dictExcelVo;
                }).collect(Collectors.toList());

        //2.3 将转换后的 实体类对象的集合 写到excel文件中 导出
        //response.getOutputStream()： 获取response的输出流，可以向响应体中写数据
        //   响应头： 告诉客户端  响应体内容的类型，客户端应该如何解析: excel文件可以告诉客户端他自己是一个文件 浏览器需要下载
        // content-type: 如果响应体是普通的浏览器可以识别解析的内容  可以通过它配置
        //content-disposition: 如果响应体内容 客户端无法解析展示， 可以通过content-disposition告诉客户端 需要下载
        //导出的文件名：一般会使用中文+时间日期
        String fileName = URLEncoder.encode("数据字典_" , "UTF-8") + LocalDateTime
                .now(ZoneId.of("+8")) //使用东八区的时间
                .format(DateTimeFormatter.ofPattern("yyyy_MM_dd")) //转成yyyy_MM_dd的日期字符串
                    +  ExcelTypeEnum.XLSX.getValue();
        //为了防止中文文件名乱码，我们可以通过 UrlEncoder的方式对文件名编码，浏览器会自动通过UrlEcoder还原
//        fileName = URLEncoder.encode(fileName)


        response.setHeader("content-disposition" , "attachment;filename="+fileName);

        //   响应体： 交给客户端的数据
        EasyExcel.write(response.getOutputStream())
                .excelType(ExcelTypeEnum.XLSX) //配置写出文件的excel类型(xlsx表示最新的格式)
                .sheet("数据字典") //指定工作簿
                .head(DictExcelVo.class) //指定如何生成excel的表头(可以通过一个类 指定 根据它的属性来生成:
                                                // 如果属性上使用了EasyExcel的注解加了别名，会按照别名生成表头)
                .doWrite(excelVos);
    }

    public static void main(String[] args) throws UnsupportedEncodingException {
        String str = "数据字典";
        // 将每一个字节转为一个%开始的字符串
        String encode = URLEncoder.encode(str, "UTF-8");
        System.out.println(encode);


        String decode = URLDecoder.decode(encode, "UTF-8");
        System.out.println(decode);

    }
}




